#pragma once

// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license

// GL.h 
//

#include <GL/glew.h>
#include "gl/wglext.h"
#include "gl/glext.h"
#include <gl/GL.h>
#include <gl/GLU.h>
#include <gl/GLUT.h>
#include "Common.h"

bool WGLisExtensionSupported(const char *extension);

#define WGL_SAMPLE_BUFFERS_ARB 0x2041
#define WGL_SAMPLES_ARB	 0x2042

extern bool arbMultisampleSupported;
extern int arbMultisampleFormat;

#define CHECK_FOR_MULTISAMPLE 1

bool InitMultisample(HWND hWnd);

inline
const PIXELFORMATDESCRIPTOR& getStandardPixelFormatDescriptor()
{
    static PIXELFORMATDESCRIPTOR pfd = 
    {
        sizeof(PIXELFORMATDESCRIPTOR),  // size of this pfd
        1,							// version number
        PFD_DRAW_TO_WINDOW |        // support window
        PFD_SUPPORT_OPENGL |        // support OpenGL
        PFD_DOUBLEBUFFER,           // double buffered
        PFD_TYPE_RGBA,              // RGBA type
        24,                         // 24-bit color depth
        0, 0, 0, 0, 0, 0,           // color bits ignored
        0,                          // no alpha buffer
        0,                          // shift bit ignored
        0,                          // no accumulation buffer
        0, 0, 0, 0,                 // accumulation bits ignored
        16,                         // 16-bit z-buffer
        0,							// no stencil buffer
        0,                          // no auxiliary buffer
        PFD_MAIN_PLANE,             // main layer
        0,                          // reserved
        0, 0, 0                     // layer masks ignored
    };
    return pfd;
}


inline bool SetupPixelFormat(CDC* dc)
{
    PIXELFORMATDESCRIPTOR pfd = getStandardPixelFormatDescriptor();
    int nPF = ChoosePixelFormat(dc->m_hDC, &pfd);
    return !!SetPixelFormat(dc->m_hDC, nPF, &pfd);
}

#pragma warning(disable : 4996)

// Returns 1 if an OpenGL error occurred, 0 otherwise.
inline bool printOglError(char *file, int line, std::vector<std::string>& msgs)
{
    msgs.clear();

    GLenum glErr;
    bool retCode = false;

    glErr = glGetError();
    while (glErr != GL_NO_ERROR)
    {
        char msg[512];
        sprintf(msg, "glError in file %s @ line %d: %s\n", file, line, gluErrorString(glErr));
        msgs.push_back(msg);
        retCode = true;
        glErr = glGetError();
    }
    return retCode;
}

#pragma warning(default : 4996)

inline void checkGlErrors(char* file, int line)
{
    std::vector<std::string> msgs;

    if(printOglError(file, line, msgs))
    {
        for(size_t i = 0; i < msgs.size(); ++i)
        {
            dbg(msgs[i]);
        }
        std::string total;
        for(size_t i = 0; i < msgs.size(); ++i)
        {
            total += (msgs[i] + "\n");
        }
        throw std::exception(total.c_str());
    }
}

#ifdef _DEBUG
#   define CHECK_GL_ERRORS() checkGlErrors(__FILE__, __LINE__)
#else 
#   define CHECK_GL_ERRORS() ((void*)0);
#endif